package cn.jtool.dig.server.configuration;

import cn.jtool.dig.common.metrics.MetricManager;
import cn.jtool.dig.common.metrics.MetricMeta;
import cn.jtool.dig.common.model.Session;
import cn.jtool.dig.common.netty.SessionManager;
import cn.jtool.dig.server.Application;
import cn.jtool.dig.server.comm.StageManager;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Configuration;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Configuration
public class MetricConfigure implements CommandLineRunner {

    @Value("${metrics.interval:60}")
    private int metricsInterval;

    @Override
    public void run(String... args) {
        try{
//            startMetrics();
        }catch (Exception ignored){

        }
    }

    public void startMetrics(){
        Thread statThread = new Thread(() -> {
            Logger statLog = LoggerFactory.getLogger("STAT");
            while (true){
                try {
                    TimeUnit.SECONDS.sleep(this.metricsInterval);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                List<Session> sessions = SessionManager.getSession(Session.SessionType.TUNNEL);
                List<Session> internalSessions = SessionManager.getSession(Session.SessionType.REAL);
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                statLog.info("*******************************************************");
                statLog.info("当前时间: {}", simpleDateFormat.format(new Date()));
                statLog.info("服务启动时间: {}", simpleDateFormat.format(Application.serverStartTime));
                statLog.info("当前共 [{}] 条内部客户端接入", CollectionUtils.isEmpty(internalSessions) ? 0 : internalSessions.size());
                if(CollectionUtils.isNotEmpty(internalSessions)){
                    internalSessions.forEach(session -> {
                        statLog.info("    链路ID: {}", session.getId());
                        statLog.info("    链路地址: {}", session.getChannelHandlerContext().channel().remoteAddress().toString());
                        statLog.info("    链路创建时间: {}", simpleDateFormat.format(session.getCreateTime()));
                        statLog.info("    链路最后交互时间: {}", simpleDateFormat.format(session.getUpdateTime()));
                    });
                }
                statLog.info("当前共 [{}] 台设备接入", CollectionUtils.isNotEmpty(sessions) ? sessions.size() : 0);
                if(CollectionUtils.isNotEmpty(sessions)) {
                    sessions.sort((o1, o2) -> (int) (o1.getId() - o2.getId()));
                    statLog.info("最小链路ID: {}", sessions.get(0).getId());
                    statLog.info("最大链路ID: {}", sessions.get(sessions.size() - 1).getId());
                }
                statLog.info("累计接收数据包数据: {}", MetricManager.getMetric(MetricMeta.receivePacketNumber));
                statLog.info("累计接收数据包大小: {}", MetricManager.getMetric(MetricMeta.receiveByteSize));
                statLog.info("累计转发数据包数量: {}", MetricManager.getMetric(MetricMeta.forwardPacketNumber));
                statLog.info("累计转发数据包大小: {}", MetricManager.getMetric(MetricMeta.forwardByteSize));
                Map<String, String> stageStatus = StageManager.status();
                statLog.info("暂存区状态: {} 条链路, {} 数据", stageStatus.get("number"), stageStatus.get("size"));
            }
        });
        statThread.setName("stat-metric-thread");
        statThread.start();
    }
}
